package com.ccit.money.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ccit.common.exception.GymException;
import com.ccit.common.result.Result;
import com.ccit.common.utils.RedisUtils;
import com.ccit.common.utils.UploadUtil;
import com.ccit.model.Money;
import com.ccit.model.vo.money.*;
import com.ccit.money.service.TypeService;
import com.ccit.money.service.impl.MoneyServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "资金管理")
@RestController
@RequestMapping("/money")
public class MoneyController {
    @Autowired
    private MoneyServiceImpl moneyService;

    @Autowired
    private TypeService typeService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private UploadUtil uploadUtil;

    @ApiOperation(value = "获取所有资金")
    @GetMapping("/getAllMoney")
    public Result getAllPhoneIntegral() {
        String key = "AllMoney";
        boolean hasKey = redisUtils.hasKey(key);
        List<Money> moneyList;
        if (hasKey) {
            moneyList = (List<Money>)redisUtils.get(key);
        } else {
            List<Money> list = moneyService.list();
            moneyList = list;
            redisUtils.set(key, moneyList);
        }

        return Result.ok(moneyList);
    }

    @ApiOperation(value = "分页获取资金")
    @GetMapping("/getPageMoney/{current}/{size}")
    public Result getMoneyByPage(@PathVariable long current, @PathVariable long size,@RequestBody(required = false) Money money) {
        Page<Money> page;
        String key = "MoneyPage:" + current + ":" + size;
        if (money!=null){
            if (money.getMoneyType()!=null && money.getTypeName()!=null){
                key = "MoneyPage:"+ money.getMoneyType() + ":" + money.getTypeName() + ":" + current + ":" + size;
            }else if (money.getTypeName()!=null){
                key = "MoneyPage:" + money.getTypeName() + ":" + current + ":" + size;
            }else if (money.getMoneyType()!=null){
                key = "MoneyPage:"+ money.getMoneyType() +  ":" + current + ":" + size;
            }
        }
        boolean hasKey = redisUtils.hasKey(key);
        System.out.println(money);
        if (hasKey){
            System.out.println("==============redis=====================");
            page = (Page<Money>)redisUtils.get(key);
        }else {
            QueryWrapper<Money> wrapper = new QueryWrapper<Money>();
            if (money!=null){
                if (money.getTypeName()!=null && money.getMoneyType()!=null){
                    wrapper.lambda()
                            .eq(Money::getMoneyType,money.getMoneyType())
                            .eq(Money::getTypeName,money.getTypeName())
                            .orderByDesc(Money::getAmout)
                            .orderByDesc(Money::getTime);
                }else if (money.getTypeName()!=null){
                    wrapper.lambda()
                            .eq(Money::getTypeName,money.getTypeName())
                            .orderByDesc(Money::getAmout)
                            .orderByDesc(Money::getTime);
                }else if (money.getMoneyType()!=null){
                    wrapper.lambda()
                            .eq(Money::getMoneyType,money.getMoneyType())
                            .orderByDesc(Money::getAmout)
                            .orderByDesc(Money::getTime);

                }
            }else {
                wrapper.lambda()
                        .orderByDesc(Money::getAmout)
                        .orderByDesc(Money::getTime);
            }

            Page<Money> moneyPage = new Page<>(current, size);
            page = moneyService.page(moneyPage, wrapper);
            redisUtils.set(key,page);
        }
        return Result.ok(page);
    }

    @ApiOperation(value = "查询总资金")
    @GetMapping("/getAllSimMoney")
    public Result getAllMoney() {
        AllMoneyrVo allMoneyrVo;
        String redisKey = "AllSimMoney";
        boolean hasKey = redisUtils.hasKey(redisKey);
        if (hasKey){
            System.out.println("==============redis=====================");
            allMoneyrVo = (AllMoneyrVo)redisUtils.get(redisKey);
        }else {
            //查询所有资金记录
            QueryWrapper<Money> wrapper = new QueryWrapper<Money>();
            wrapper.lambda()
                    .orderByDesc(Money::getAmout)
                    .orderByDesc(Money::getTime);
            List<Money> list = moneyService.list(wrapper);

            //根据种类分组
            Map<String, List<Money>> collect = list.stream().collect(Collectors.groupingBy(money -> money.getMoneyType()));
            allMoneyrVo = new AllMoneyrVo();
            //收入支出总数
            Map<String,Double> summarize = new HashMap<>();
            collect.forEach((key,value)->{
                double sum = value.stream().mapToDouble(Money::getAmout).sum();
                System.out.println(sum);
                System.out.println(key);
                summarize.put(key,sum);
            });
            Map<String, List<SimMoneyVo>> moneyMap = new HashMap<>();
            //将种类存进去
            collect.forEach((key,value) ->{
                List<SimMoneyVo> simMoneyVos = new ArrayList<>();
                Map<String, List<Money>> listMap = value.stream().collect(Collectors.groupingBy(money -> money.getTypeName()));
                listMap.forEach((s, monies) -> {
                    SimMoneyVo simMoneyVo = new SimMoneyVo();
                    simMoneyVo.setName(s);
                    simMoneyVo.setAccount(0);
                    monies.forEach(money -> {
                        simMoneyVo.setAccount(money.getAmout()+ simMoneyVo.getAccount());
                    });
                    simMoneyVo.setRate(simMoneyVo.getAccount() / summarize.get(key));
                    simMoneyVos.add(simMoneyVo);
                });
                List<SimMoneyVo> collect1 = simMoneyVos.stream().sorted(Comparator.comparing(SimMoneyVo::getAccount,
                        Comparator.nullsFirst(Double::compareTo)).reversed())
                        .collect(Collectors.toList());
                moneyMap.put(key,collect1);
            });

            allMoneyrVo.setMoneyMap(moneyMap);
            allMoneyrVo.setSummarize(summarize);
            redisUtils.set(redisKey,allMoneyrVo);
        }
        return Result.ok(allMoneyrVo);
    }

    @ApiOperation(value = "查询本月资金")
    @GetMapping("/getMonthSimMoney")
    public Result getMonthMoney(){
         MoneyMonthVo moneyMonthVo;
        String redisKey = "MonthMoney";
        boolean hasKey = redisUtils.hasKey(redisKey);
        if (hasKey){
            System.out.println("==============redis=====================");
            moneyMonthVo = (MoneyMonthVo)redisUtils.get(redisKey);
        }else {
             //查询本月资金记录
            String[] split = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString().split("-");
            QueryWrapper<Money> wrapper = new QueryWrapper<Money>();
            try {
                Date startTime1 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + (Integer.valueOf(split[1]) + 1) + "-00");
                Date endTime1 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + split[1] + "-01");
                System.out.println(startTime1);
                System.out.println(endTime1);
                wrapper.lambda()
                        .le(Money::getTime,startTime1)
                        .ge(Money::getTime,endTime1)
                        .orderByDesc(Money::getAmout)
                        .orderByDesc(Money::getTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }

            List<Money> list = moneyService.list(wrapper);

            //根据种类分组
            Map<String, List<Money>> collect = list.stream().collect(Collectors.groupingBy(money -> money.getMoneyType()));
            moneyMonthVo = new MoneyMonthVo();
            moneyMonthVo.setExtMoney(new HashMap<>());
            //收入支出总数
            Map<String,Double> summarize = new HashMap<>();
            collect.forEach((key,value)->{
                double sum = value.stream().mapToDouble(Money::getAmout).sum();
                System.out.println(sum);
                System.out.println(key);
                summarize.put(key,sum);

            });
            QueryWrapper<Money> wra = new QueryWrapper<Money>();
            try {
                Date startTime2 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + (Integer.valueOf(split[1]) + 1) + "-00");
                Date endTime2 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + split[1] + "-01");
                wra.lambda()
                        .le(Money::getTime,startTime2)
                        .ge(Money::getTime,endTime2)
                        .orderByDesc(Money::getAmout);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            List<Money> moneyList = moneyService.list(wra);
            Map<String, List<Money>> extCollect = moneyList.stream().collect(Collectors.groupingBy(money -> money.getMoneyType()));
            extCollect.forEach((key,value) ->{
                //存极值
                List<Money> ext = new ArrayList<>();
                ext.add(value.get(0));
                ext.add(value.get(value.size()-1));
                moneyMonthVo.getExtMoney().put(key,ext);
            });

            Map<String, List<SimMoneyVo>> moneyMap = new HashMap<>();
            collect.forEach((key,value) ->{
                List<SimMoneyVo> simMoneyVos = new ArrayList<>();
                Map<String, List<Money>> listMap = value.stream().collect(Collectors.groupingBy(money -> money.getTypeName()));
                listMap.forEach((s, monies) -> {
                    SimMoneyVo simMoneyVo = new SimMoneyVo();
                    simMoneyVo.setName(s);
                    simMoneyVo.setAccount(0);
                    monies.forEach(money -> {
                        simMoneyVo.setAccount(money.getAmout()+ simMoneyVo.getAccount());
                    });
                    simMoneyVo.setRate(simMoneyVo.getAccount() / summarize.get(key));
                    simMoneyVos.add(simMoneyVo);
                });
                List<SimMoneyVo> collect1 = simMoneyVos.stream().sorted(Comparator.comparing(SimMoneyVo::getAccount,
                        Comparator.nullsFirst(Double::compareTo)).reversed())
                        .collect(Collectors.toList());
                moneyMap.put(key,collect1);
            });

            //查询上月资金记录
            QueryWrapper<Money> queryWrapper = new QueryWrapper<Money>();
            try {
                Date startTime3 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + split[1] + "-00");
                Date endTime3 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + (Integer.valueOf(split[1]) - 1) + "-01");
                queryWrapper.lambda()
                        .le(Money::getTime,startTime3)
                        .ge(Money::getTime,endTime3)
                        .orderByDesc(Money::getAmout)
                        .orderByDesc(Money::getTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            List<Money> lastList = moneyService.list(queryWrapper);

            //上个月分类
            Map<String, List<Money>> lastCollect = lastList.stream().collect(Collectors.groupingBy(money -> money.getMoneyType()));

            //上个月收入支出总数
            Map<String,Double> lastSummarize = new HashMap<>();
            lastCollect.forEach((key,value)->{
                double sum = value.stream().mapToDouble(Money::getAmout).sum();
                lastSummarize.put(key,sum);
            });
            Map<String,Double> map = new HashMap<>();
            System.out.println(summarize);
            System.out.println(lastSummarize);
            summarize.forEach((key,value)->{
                System.out.println(value);
                System.out.println(lastSummarize.get(key));
               map.put(key,(value - lastSummarize.get(key)) / lastSummarize.get(key)) ;
            });

            System.out.println(map);
            moneyMonthVo.setMoneyMap(moneyMap);
            moneyMonthVo.setRate(map);
            redisUtils.set(redisKey,moneyMonthVo);
        }
        return Result.ok(moneyMonthVo);
    }

    @ApiOperation(value = "查询当天资金")
    @GetMapping("/getTodaySimMoney")
    public Result getToMoney() {
        ToDayMoney toDayMoney;
        String redisKey = "ToMoney";
        boolean hasKey = redisUtils.hasKey(redisKey);
        if (hasKey){
            System.out.println("==============redis=====================");
            toDayMoney = (ToDayMoney)redisUtils.get(redisKey);
        }else {
            //查询本月资金记录
            String[] split = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString().split("-");
            QueryWrapper<Money> wrapper = new QueryWrapper<Money>();
            try {
                Date startTime1 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + split[1]+ "-" + split[2]);
                Date endTime1 = new SimpleDateFormat("yyyy-MM-dd").parse(split[0]+ "-" + split[1]+ "-" + (Integer.valueOf(split[2])+1));
                wrapper.lambda()
                        .ge(Money::getTime,startTime1)
                        .le(Money::getTime,endTime1)
                        .orderByDesc(Money::getAmout)
                        .orderByDesc(Money::getTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }

            List<Money> list = moneyService.list(wrapper);
            System.out.println(list+"本日========================================================");

            //根据种类分组
            Map<String, List<Money>> collect = list.stream().collect(Collectors.groupingBy(money -> money.getMoneyType()));
            toDayMoney = new ToDayMoney();
            //收入支出总数
            Map<String,Double> summarize = new HashMap<>();
            collect.forEach((key,value)->{
                double sum = value.stream().mapToDouble(Money::getAmout).sum();
                summarize.put(key,sum);
            });

            Map<String, List<SimMoneyVo>> moneyMap = new HashMap<>();
            //将种类存进去
            collect.forEach((key,value) ->{
                List<SimMoneyVo> simMoneyVos = new ArrayList<>();
                if (key.equals("收入")){
                    Money money = value.stream().max(Comparator.comparing(Money::getAmout)).get();
                    toDayMoney.setMax(money.getAmout());
                }
                Map<String, List<Money>> listMap = value.stream().collect(Collectors.groupingBy(money -> money.getTypeName()));
                listMap.forEach((s, monies) -> {
                    SimMoneyVo simMoneyVo = new SimMoneyVo();
                    simMoneyVo.setName(s);
                    simMoneyVo.setAccount(0);
                    monies.forEach(money -> {
                        simMoneyVo.setAccount(money.getAmout()+ simMoneyVo.getAccount());
                    });
                    simMoneyVo.setRate(simMoneyVo.getAccount() / summarize.get(key));
                    simMoneyVos.add(simMoneyVo);
                });
                List<SimMoneyVo> collect1 = simMoneyVos.stream().sorted(Comparator.comparing(SimMoneyVo::getAccount,
                        Comparator.nullsFirst(Double::compareTo)).reversed())
                        .collect(Collectors.toList());
                moneyMap.put(key,collect1);
            });
            toDayMoney.setMoneyMap(moneyMap);
            redisUtils.set(redisKey,toDayMoney);
        }
        return Result.ok(toDayMoney);
    }

    @ApiOperation(value = "修改资金")
    @PutMapping("/updateIntegral")
    public Result updateMoney(@RequestBody Money money) {
            boolean flag = moneyService.updateById(money);
            if (flag) {
                redisUtils.deleteRedisKeys("AllMoney");
                redisUtils.deleteRedisKeys("MoneyPage");
                redisUtils.deleteRedisKeys("AllSimMoney");
                redisUtils.deleteRedisKeys("MonthMoney");
                redisUtils.deleteRedisKeys("ToMoney");
                return Result.ok();
            } else {
                return Result.fail().message("修改失败");
            }

    }

    @ApiOperation(value = "删除资金")
    @DeleteMapping("/deleteMoney/{id}")
    public Result removeIntegral(@PathVariable("id") Integer id) {
        Money money = moneyService.getById(id);
        if (money==null){
            throw new GymException(202,"查无此资金");
        }
        boolean byId = moneyService.removeById(id);
            if (byId) {
                redisUtils.deleteRedisKeys("AllMoney");
                redisUtils.deleteRedisKeys("MoneyPage");
                redisUtils.deleteRedisKeys("AllSimMoney");
                redisUtils.deleteRedisKeys("MonthMoney");
                redisUtils.deleteRedisKeys("ToMoney");
                return Result.ok("删除成功");
            } else throw new GymException(202, "无此积分用户");
    }

    @ApiOperation(value = "保存资金")
    @PostMapping("/saveMoney")
    public Result saveMoney(@RequestBody MoneyVo moneyVo) {
        Money money = new Money();
        money.setMoneyType(moneyVo.getMoneyType());
        money.setTypeName(moneyVo.getTypeName());
        money.setAmout(moneyVo.getAmout());
        boolean result = moneyService.save(money);
        if (result) {
            redisUtils.deleteRedisKeys("AllMoney");
            redisUtils.deleteRedisKeys("MoneyPage");
            redisUtils.deleteRedisKeys("AllSimMoney");
            redisUtils.deleteRedisKeys("MonthMoney");
            redisUtils.deleteRedisKeys("ToMoney");
            return Result.ok("添加成功");
        } else
            throw new GymException(203, "服务异常");
    }

    @ApiOperation(value = "保存资金")
    @PostMapping("apiMoney")
    public boolean apiSaveMoney(@RequestBody MoneyVo moneyVo) {
        Money money = new Money();
        money.setMoneyType(moneyVo.getMoneyType());
        money.setTypeName(moneyVo.getTypeName());
        money.setAmout(moneyVo.getAmout());
        boolean result = moneyService.save(money);
        if (result) {
            redisUtils.deleteRedisKeys("AllMoney");
            redisUtils.deleteRedisKeys("MoneyPage");
            redisUtils.deleteRedisKeys("AllSimMoney");
            redisUtils.deleteRedisKeys("MonthMoney");
            redisUtils.deleteRedisKeys("ToMoney");
            return true;
        } else
            return false;
    }
}
